from django.shortcuts import get_object_or_404
from django.utils import timezone
from rest_framework import viewsets, permissions, status
from rest_framework.response import Response

from utils.custom_model_viewSet import CustomModelViewSet
from .models import Department, Menu, MenuMeta, Role, RolePermission
from .serializers import (
    DepartmentSerializer, MenuSerializer, MenuMetaSerializer, RoleSerializer
)
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework.decorators import action


class DepartmentViewSet(CustomModelViewSet):
    """部门管理视图集"""
    queryset = Department.objects.filter(pid__isnull=True).order_by('id', 'status')
    serializer_class = DepartmentSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['status', 'pid']
    search_fields = ['name']
    ordering_fields = ['create_time', 'name']

    def perform_create(self, serializer):
        # 自动设置创建时间
        if 'create_time' not in serializer.validated_data:
            serializer.validated_data['create_time'] = timezone.now()
        serializer.save()

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        pk = kwargs['pk']
        instance = Department.objects.get(pk=pk)
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        headers = self.get_success_headers(serializer.data)
        return self._build_response(
            data=serializer.data,
            message="ok",
            status=status.HTTP_200_OK,
            headers=headers
        )

    def destroy(self, request, *args, **kwargs):
        pk = kwargs['pk']
        instance = Department.objects.get(pk=pk)
        self.perform_destroy(instance)
        return self._build_response(
            message="ok",
            status=status.HTTP_200_OK,
        )

    @action(detail=False, methods=['get'])
    def tree(self, request):
        """获取部门树形结构"""
        queryset = self.get_queryset().filter(pid__isnull=True)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class MenuMetaViewSet(viewsets.ModelViewSet):
    """菜单元数据视图集"""
    queryset = MenuMeta.objects.all()
    serializer_class = MenuMetaSerializer


class MenuViewSet(CustomModelViewSet):
    """菜单管理视图集"""
    queryset = Menu.objects.filter(pid__isnull=True).order_by('id', 'status')
    serializer_class = MenuSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['status', 'type', 'pid', 'name']
    search_fields = ['name', 'path', 'auth_code']
    ordering_fields = ['meta__order', 'create_time']

    @action(detail=False, methods=['get'])
    def tree(self, request):
        """获取菜单树形结构"""
        queryset = self.get_queryset().filter(pid__isnull=True)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['get'], url_path='name-exists')
    def name_exists(self, request):
        return self._build_response()

    @action(detail=False, methods=['get'], url_path='name-search')
    def name_search(self, request):
        name = request.GET.get('name')
        pk = request.GET.get('id', None)
        queryset = Menu.objects.all()
        if pk:
            queryset = queryset.exclude(pk=pk)
        if name:
            queryset = queryset.filter(name=name)
        has_menu_name = queryset.exists()
        print(has_menu_name, 'has_menu_name')
        return self._build_response(data=has_menu_name)

    @action(detail=False, methods=['get'], url_path='path-exists')
    def path_exists(self, request):
        return self._build_response()


    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        pk = kwargs['pk']
        instance = Menu.objects.get(pk=pk)
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        headers = self.get_success_headers(serializer.data)
        return self._build_response(
            data=serializer.data,
            message="ok",
            status=status.HTTP_200_OK,
            headers=headers
        )

    def destroy(self, request, *args, **kwargs):
        pk = kwargs['pk']
        instance = Menu.objects.get(pk=pk)
        self.perform_destroy(instance)
        return self._build_response(
            message="ok",
            status=status.HTTP_200_OK,
        )


class RoleViewSet(CustomModelViewSet):
    """角色管理视图集"""
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['status']
    search_fields = ['name']
    ordering_fields = ['create_time']

    @action(detail=True, methods=['post'])
    def assign_permissions(self, request, pk=None):
        """分配角色权限"""
        role = self.get_object()
        menu_ids = request.data.get('menu_ids', [])

        # 清除原有权限
        role.permissions.clear()

        # 添加新权限
        for menu_id in menu_ids:
            menu = get_object_or_404(Menu, id=menu_id)
            RolePermission.objects.create(role=role, menu=menu)

        serializer = self.get_serializer(role)
        return Response(serializer.data)

    def create(self, request, *args, **kwargs):
        # 获取请求数据
        data = request.data.copy()
        permissions = data.pop('permissions', [])  # 提取权限列表

        # 创建角色（不包含权限）
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        role = serializer.save()

        # 处理权限关联（可根据需求自定义）
        if permissions:
            try:
                # 验证权限ID是否存在
                valid_permissions = Menu.objects.filter(id__in=permissions)

                # 创建中间表记录（如果需要保存额外字段）
                for menu in valid_permissions:
                    RolePermission.objects.create(
                        role=role,
                        menu=menu,
                    )
            except Exception as e:
                # 如果关联失败，删除已创建的角色
                role.delete()
                return Response(
                    {'error': f'权限关联失败: {str(e)}'},
                    status=status.HTTP_400_BAD_REQUEST
                )

        headers = self.get_success_headers(serializer.data)
        return self._build_response(
            data=serializer.data,
            message="ok",
            status=status.HTTP_200_OK,
            headers=headers
        )
